/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nokia.iap.ui.lib.onebutton;

import com.nokia.mid.payment.IAPClientPaymentListener;
import com.nokia.mid.payment.IAPClientPaymentManager;
import com.nokia.mid.payment.IAPClientProductData;
import com.nokia.mid.payment.IAPClientUserAndDeviceData;
import com.nokia.mid.ui.FullCanvas;
import java.util.Vector;
import javax.microedition.lcdui.*;
/**
 * @author zinin
 */
public class OneButtonIAP extends FullCanvas implements IAPClientPaymentListener {
    
    public IAPClientPaymentManager iapClient;
    public static String productID;
    public static final String DRM_PATH = "drm/data/resourceid_";
    public static String lockedFname;

    private int spacing = 2;
    private int fontHeight; //calculated values
    private int width;
    private int height;
    private boolean init;

    public StringBuffer screenBuf = new StringBuffer();
    public final int KLineBreak = '\n';
    public final String KLabelMark = "<l>";
    public final String KHorzCenterMark = "<h>";
    public final String KIndentationMark = "<i>";
    
    private IAPCompletionListener clientComponent;

    public int prodStatus;
    public String prodTitle;
    public String prodDescr;
    public String prodLongDescr;
    public int prodDRM;
    public String prodPrice;
    public String prodTicket;
    
    private boolean isBought;

    private static GxButtonStart buttonStart;
    private static GxColorTheme theme = null;
    public static GxMasterBar masterBar = null;
    private static GxButtonBuy buttonBuy = null;
    private static GxButtonCancelBuy buttonBuyCancel = null;
    private static GxButtonDone buttonDone = null;
    
    private Vector controlArr = new Vector(2);
    private int selectedIdx;
    private boolean isHalted;
    private int textAreaHeight;
    /**
     * constructor
     */
    public OneButtonIAP(IAPCompletionListener aClient, String productID, String lockedFname){
        try {
            clientComponent = aClient;
            iapClient = IAPClientPaymentManager.getIAPClientPaymentManager();
            IAPClientPaymentManager.setIAPClientPaymentListener(this);
            OneButtonIAP.productID = productID;
            OneButtonIAP.lockedFname = lockedFname;
            theme = new GxColorTheme(clientComponent.clientDisplay());
            
            buttonStart = new GxButtonStart(this, theme);
            int firstButtonAboveMasterBarY = getHeight() - 3 * buttonStart.getHeight();
            buttonStart.setPosition((getWidth() - buttonStart.getWidth()) / 2, firstButtonAboveMasterBarY);
            masterBar = new GxMasterBar(this, theme, 4);
            textAreaHeight = firstButtonAboveMasterBarY - buttonStart.getHeight() / 2;
            
            buttonBuy = new GxButtonBuy(this, theme);
            buttonBuy.setVisible(false);
            buttonBuyCancel = new GxButtonCancelBuy(this, theme);
            buttonBuyCancel.setVisible(false);
            
            int secondButtonOffsetY = buttonStart.getHeight() * 2;
            if(getHeight() < 320){
                firstButtonAboveMasterBarY = getHeight() - 2 * buttonStart.getHeight() - 5;
                secondButtonOffsetY = buttonStart.getHeight() - 5;
            }
            buttonBuyCancel.setPosition((getWidth() - buttonBuyCancel.getWidth()) / 2, firstButtonAboveMasterBarY);
            buttonBuy.setPosition((getWidth() - buttonBuy.getWidth()) / 2, firstButtonAboveMasterBarY - secondButtonOffsetY);
            
            buttonDone = new GxButtonDone(this, theme);
            buttonDone.setVisible(false);
            buttonDone.setPosition(buttonStart.getPositionX(), buttonStart.getPositionY());
            
            controlArr.addElement(buttonStart);
            controlArr.addElement(masterBar);
            controlArr.addElement(buttonBuy);
            controlArr.addElement(buttonBuyCancel);
            controlArr.addElement(buttonDone);
            buttonStart.setFocus(true);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * paint
     */
    public void paint(Graphics g) {
        if (!init) {
            width = getWidth();
            height = getHeight();
            init = true;
            fontHeight = g.getFont().getHeight();
        }

        int oldColor = g.getColor();
        g.setColor(theme.getBackgroundColor());
        g.fillRect(0, 0, width, height);
        g.setColor(oldColor);
        
        paintText(g);
        masterBar.paint(g);
        buttonStart.paint(g);
        buttonBuy.paint(g);
        buttonBuyCancel.paint(g);
        buttonDone.paint(g);
    }

    private void paintText(Graphics g) {
        if(screenBuf.length() == 0)
            return;
        
        int oldColor = g.getColor();

        ParseBuf lines = parseText(screenBuf.toString(), KLineBreak);
        int posX;
        // always vertically center the text
        int posY= (textAreaHeight - lines.length * (fontHeight + spacing)) / 2 + fontHeight + spacing;
        for(int i=0; i < lines.length; i++){
            if(lines.buf[i] == null){
                break;
            }
            posX = spacing;
            g.setColor(0, 0x33, 0x99);
            String outText = lines.buf[i];
            
            if(outText.startsWith(KLabelMark)){
                g.setColor(0x99, 0, 0);
                outText = outText.substring(KLabelMark.length());
            }

            int justification = Graphics.LEFT;
            
            if(outText.startsWith(KHorzCenterMark)){
                justification = Graphics.HCENTER;
                posX = width / 2;
                outText = outText.substring(KHorzCenterMark.length());
            } else if(outText.startsWith(KIndentationMark)){
                posX += fontHeight;
                outText = outText.substring(KIndentationMark.length());
            }
          
            g.drawString(outText, posX, posY, Graphics.TOP|justification);
            posY += fontHeight + spacing;
        }
        g.setColor(oldColor);
    }

    public void cancelProcess() {
        isHalted = true;
    }

    public void cancelImmediatelly(){
        masterBar.setToBegin();
        buttonStart.setToInitialState();
        isHalted = false;

        buttonStart.setVisible(true);
        buttonBuy.setVisible(false);
        buttonBuyCancel.setVisible(false);
        buttonDone.setVisible(false);

        setButtonFocus(buttonStart);
    }
    
    private void setfocusNext() {
        ((GxControl) controlArr.elementAt(selectedIdx)).setFocus(false);
        int prevVal = selectedIdx;
        for(int i = selectedIdx + 1; i < controlArr.size(); i++){
            if(!((GxControl) controlArr.elementAt(i)).isHidden()){
                selectedIdx = i;
                break;
            }
        }
        if(prevVal == selectedIdx){
            for(int i = 0; i < selectedIdx; i++){
                if(!((GxControl) controlArr.elementAt(i)).isHidden()){
                    selectedIdx = i;
                    break;
                }
            }
        }
        ((GxControl) controlArr.elementAt(selectedIdx)).setFocus(true);
    }

    private void setButtonFocus(GxControl control) {
        boolean focused = false;
        for(int i = selectedIdx + 1; i < controlArr.size(); i++){
            focused = ((GxControl) controlArr.elementAt(i)).equals(control);
            if(focused){
                selectedIdx = i;
            }
            ((GxControl) controlArr.elementAt(i)).setFocus(focused);
        }
    }
    
    class ParseBuf
    {
        public final int maxLine = 20;
        public String [] buf = new String[maxLine];
        public int length;
    }

    private ParseBuf parseText(String text, int separator){
        ParseBuf result = new ParseBuf();
        for(int begin=0, end=0, i=0; i < result.maxLine; i++){
            end = text.indexOf(separator, begin);
            result.length++;
            if(end == -1){
                result.buf[i] = text.substring(begin).trim();
                break;
            }else{
                result.buf[i] = text.substring(begin, end).trim(); 
                end++; //NOTE: that allows to increment indexes 'begin' and 'end'
            }
            begin = end;
        }
        return result;
    }

    public void exitIAP(){
        clientComponent.notifyIAPComplete(isBought);
    }
    
    /**
     * Called when a key is pressed.
     */
    protected void keyPressed(int keyCode) {
        if((keyCode == UP || keyCode == -1) ||
            (keyCode == RIGHT || keyCode == -4) ||
                (keyCode == DOWN || keyCode == -2) ||
                     (keyCode == LEFT || keyCode == -3)){
            setfocusNext();
        }else{
            ((GxControl) controlArr.elementAt(selectedIdx)).execute();
        }
        repaint(); //update text on screen
    }

    /**
     * Called when a key is released.
     */
    protected void keyReleased(int keyCode) {
    }

    /**
     * Called when a key is repeated (held down).
     */
    protected void keyRepeated(int keyCode) {
    }

    /**
     * Called when the pointer is dragged.
     */
    protected void pointerDragged(int x, int y) {
    }

    /**
     * Called when the pointer is pressed.
     */
    protected void pointerPressed(int x, int y) {
    }

    /**
     * Called when the pointer is released.
     */
    protected void pointerReleased(int x, int y) {
        if( masterBar.onTouch(x, y) ||
            buttonStart.onTouch(x, y) ||
                buttonBuy.onTouch(x, y) ||
                    buttonBuyCancel.onTouch(x, y) ||
                        buttonDone.onTouch(x, y)){
            repaint(); //update text on screen
        }
    }

    public void productDataReceived(int status, IAPClientProductData pd) {
        screenBuf.delete(0, screenBuf.length());
        if(isHalted){
            cancelImmediatelly();
        }else{
            prodStatus = status;
            prodTitle = pd.getTitle();
            prodDescr = pd.getShortDescription();
            prodLongDescr = pd.getLongDescription();
            prodDRM = pd.getDrmProtection();
            prodPrice = pd.getPrice();

            screenBuf.append(KHorzCenterMark + "PRODUCT\n");
            screenBuf.append(KIndentationMark + prodDescr + "\n");
            screenBuf.append(KLabelMark + "price:\n");
            screenBuf.append(KIndentationMark + String.valueOf(prodPrice) + "\n");
            
            setButtonFocus(buttonBuy);
            
            buttonStart.setVisible(false);
            buttonBuy.setVisible(true);
            buttonBuyCancel.setVisible(true);
            masterBar.advance();
        }
        repaint(); //update text on screen
    }

    public void productDataListReceived(int status, IAPClientProductData[] productDataList) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void purchaseCompleted(int status, String purchaseTicket) {
        isBought = (status == IAPClientPaymentListener.OK || status == IAPClientPaymentListener.RESTORABLE);
        prodStatus = status;
        prodTicket = purchaseTicket;

        buttonBuyCancel.setVisible(false);
        buttonBuy.setVisible(false);
        buttonDone.setVisible(true);

        setButtonFocus(buttonDone);
        
        screenBuf.delete(0, screenBuf.length());
        if(isBought){
            screenBuf.append(KHorzCenterMark + "Thank you\n");
            screenBuf.append(KHorzCenterMark + "for buying!\n");
        }else{
            screenBuf.append(KHorzCenterMark + "PURCHASING ERROR\n");
            screenBuf.append(KLabelMark + "status:\n");
            screenBuf.append(KIndentationMark).append(String.valueOf(prodStatus)).append("\n");
        }
        masterBar.advance();
    }

    public void restorationCompleted(int status, String purchaseTicket) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void restorableProductsReceived(int status, IAPClientProductData[] productDataList) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void userAndDeviceDataReceived(int status, IAPClientUserAndDeviceData ud) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
